package com.lemon.exam.common.util;

import com.alibaba.fastjson2.JSON;
import com.lemon.exam.common.entity.vo.SSEMessageVO;
import com.lemon.exam.common.enums.CodeEnum;
import com.lemon.exam.common.web.Result;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.function.Function;

/**
 * 类对象
 *
 * @author Lemon
 * @since 2025/4/4 21:33
 */
public final class ResponseUtil {

    /**
     * 响应成功
     *
     * @param <T>
     * @return
     */
    public static <T> Function<T, Mono<? extends ServerResponse>> ok() {
        return data -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.ok(data));
    }

    /**
     * 响应成功
     *
     * @param <T>
     * @return
     */
    public static <T> Mono<? extends ServerResponse> ok(T data) {
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.ok(data));
    }

    /**
     * 响应成功
     *
     * @param response
     * @return
     */
    public static Mono<Void> ok(ServerHttpResponse response) {
        //1.设置响应码
        response.setStatusCode(HttpStatus.OK);
        //2.设置响应头为json
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        //3.包装对象并转换为JSON字节数组
        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(Result.ok()));
        return response.writeWith(Mono.just(dataBuffer));
    }

    /**
     * 响应成功
     *
     * @param response
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Mono<Void> ok(ServerHttpResponse response, T data) {
        //1.设置响应码
        response.setStatusCode(HttpStatus.OK);
        //2.设置响应头为json
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        //3.包装对象并转换为JSON字节数组
        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(Result.ok(data)));
        return response.writeWith(Mono.just(dataBuffer));
    }

    /**
     * 响应失败
     *
     * @return
     */
    public static Mono<? extends ServerResponse> err(String message) {
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.err(message));
    }

    /**
     * 响应失败
     *
     * @return
     */
    public static Mono<? extends ServerResponse> err(int code, String message) {
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.err(code, message));
    }

    /**
     * 响应失败
     *
     * @return
     */
    public static Function<Throwable, Mono<? extends ServerResponse>> err() {
        return throwable -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.err(throwable.getMessage()));
    }

    /**
     * 响应失败
     *
     * @return
     */
    public static Function<Throwable, Mono<? extends ServerResponse>> err(int code) {
        return throwable -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(Result.err(code, throwable.getMessage()));
    }

    /**
     * 响应失败
     *
     * @param response
     * @param codeEnum
     * @return
     */
    public static Mono<Void> err(ServerHttpResponse response, CodeEnum codeEnum) {
        return err(response, codeEnum.getCode(), codeEnum.getMessage());
    }

    /**
     * 响应失败
     *
     * @param response
     * @param code
     * @param data
     * @return
     */
    public static Mono<Void> err(ServerHttpResponse response, int code, String data) {
        //1.设置响应码
        response.setStatusCode(HttpStatus.OK);
        //2.设置响应头为json
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        //3.包装对象并转换为JSON字节数组
        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONBytes(Result.err(code, data)));
        return response.writeWith(Mono.just(dataBuffer));
    }

    /**
     * SSE响应失败
     *
     * @param response
     * @param codeEnum
     * @return
     */
    public static Mono<Void> sse(ServerHttpResponse response, CodeEnum codeEnum) {
        return sse(response, codeEnum.getCode(), codeEnum.getMessage());
    }

    /**
     * SSE响应失败
     *
     * @param response
     * @param code
     * @param data
     * @return
     */
    public static Mono<Void> sse(ServerHttpResponse response, int code, String data) {
        //1.设置响应头
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().setContentType(MediaType.TEXT_EVENT_STREAM);

        //2.创建 SSE 格式数据
        String sseData = "data: %s\n\n".formatted(JSON.toJSONString(SSEMessageVO.err(code, data)));

        //3.写入响应并返回
        return response.writeWith(Mono.just(response.bufferFactory().wrap(sseData.getBytes(StandardCharsets.UTF_8))));
    }
}
